package com.gt.config;

import com.gt.contant.FilterOrder;
import com.gt.filter.LogMdcFilter;
import com.gt.filter.RequestWrapperFilter;
import com.gt.interceptor.PublicDecryptInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.Filter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;

/**
 * @功能说明：拦截器
 * @作者： 黄和润
 * @创建日期：2021/8/23
 * @版本号：V1.0
 */
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private PublicDecryptInterceptor publicDecryptInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(publicDecryptInterceptor)
                .addPathPatterns("/public/**")
                .addPathPatterns("/manager/favorCoupon")
                .addPathPatterns("/manager/getRecordById")
                .order(1);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        // 解决静态资源无法访问
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        // 解决swagger无法访问
        registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        // 解决swagger的js文件无法访问
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
    /**
     * mdc过滤器
     */
    @Bean
    public FilterRegistrationBean mdcFilterRegistration(LogMdcFilter logMdcFilter) {
        FilterRegistrationBean registration = new FilterRegistrationBean(logMdcFilter);
        registration.addUrlPatterns("/*");
        registration.setOrder(FilterOrder.FILTER_ORDER_OF_MDC);
        return registration;
    }
    /**
     * Filter - 用于body解密
     */
    @Bean
    public FilterRegistrationBean addRequestWrapperFilter() {
        FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new RequestWrapperFilter());
        registration.setName("RequestWrapperFilter");
        registration.addUrlPatterns("/*");
        registration.setOrder(FilterOrder.FILTER_ORDER_OF_WRAPPER);
        return registration;
    }
    /**
     * wjh
     * 2024/1/28
     * 解决使用@Responsebody注解并且返回值类型为String时，返回的string字符串带有双引号
     */
    private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
        return new MappingJackson2HttpMessageConverter(){
            @Override
            protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
                if(object instanceof String){
                    StreamUtils.copy((String)object, Charset.defaultCharset(), outputMessage.getBody());
                }else{
                    super.writeInternal(object, type, outputMessage);
                }
            }
        };
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = mappingJackson2HttpMessageConverter();
        converter.setSupportedMediaTypes(new LinkedList<MediaType>(){{
            add(MediaType.TEXT_HTML);
            add(MediaType.APPLICATION_JSON);
//            add(MediaType.ALL);
        }});
        converters.add(new StringHttpMessageConverter());
        converters.add(converter);
    }
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 解决controller返回字符串中文乱码问题
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof StringHttpMessageConverter) {
                ((StringHttpMessageConverter)converter).setDefaultCharset(StandardCharsets.UTF_8);
            }
        }
    }
}
